package com.gzhryc.shared_device.bxscn.code.services;

import com.gzhryc.common.NumberTools;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.Conditions;
import com.gzhryc.jdbc.JdbcSession;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.pay.adaptation.weixin.WXPayNormalPayService;
import com.gzhryc.pay.adaptation.weixin.enums.EWXPayNormalRefundState;
import com.gzhryc.pay.adaptation.weixin.msg.normal.WXPayNormalRefundResponse;
import com.gzhryc.shared_device.base.IMemberWalletService;
import com.gzhryc.shared_device.base.IPayServiceFactory;
import com.gzhryc.shared_device.base.enums.*;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.base.models.OrderLogContent;
import com.gzhryc.shared_device.bxscn.code.BXSCNWorkThread;
import com.gzhryc.shared_device.bxscn.code.dao.BXSCNOrderDao;
import com.gzhryc.shared_device.bxscn.code.dao.db.BXSCNOrder;
import com.gzhryc.shared_device.bxscn.code.dao.enums.BXSCNOrderEnum;
import com.gzhryc.shared_device.bxscn.code.services.dto.BXSCNOrderSearch;
import com.gzhryc.shared_device.bxscn.core.BXSCNConstants;
import com.gzhryc.shared_device.bxscn.core.IBXSCNNetworkService;
import com.gzhryc.shared_device.common.payment.dao.db.WXPayOrder;
import com.gzhryc.shared_device.common.payment.dao.db.WXRefundOrder;
import com.gzhryc.shared_device.common.payment.services.WXPayOrderService;
import com.gzhryc.shared_device.common.payment.services.WXRefundOrderService;
import com.gzhryc.shared_device.iot.core.NetworkDeviceWorkThreadPool;

import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BXSCNOrderService {

    static Logger log = Logger.getLogger(BXSCNOrderService.class);

    public static BXSCNOrderService self(Date date) {
        return MultiDBTools.getService(BXSCNOrderService.class,date);
    }

    public static BXSCNOrderService self(String jdbcKey, Date date) {
        return MultiDBTools.getService(jdbcKey, BXSCNOrderService.class, date);
    }

    BXSCNOrderDao dao;

    public BXSCNOrderService(String jdbcKey, Date date) {
        dao = new BXSCNOrderDao(jdbcKey,date);
    }

    public List<BXSCNOrder> findBySearch(BXSCNOrderSearch search, Integer pageNo, Integer pageLimit){
        Conditions conditions = dao.buildConditions(search);
        conditions.and().in("leasePlaceId",search.getLeasePlaceIds());
        conditions.desc("createDate");
        try {
            return dao.findByCondition(conditions,pageNo,pageLimit);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return null;
    }

    public Long countBySearch(BXSCNOrderSearch search){
        Conditions conditions = dao.buildConditions(search);
        conditions.and().in("leasePlaceId",search.getLeasePlaceIds());
        try {
            return dao.count(conditions);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return 0L;
    }

    public BXSCNOrder getByTradeNo(String tradeNo){
        try {
            return dao.getById(tradeNo);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return null;
    }

    public BXSCNOrder getNewsByMemberIdAndState(Long memberId,Integer state){
        if(memberId != null && state != null){
            Conditions conditions = new Conditions(BXSCNOrder.class);
            conditions.and().is("memberId",memberId);
            conditions.and().is("state",state);
            conditions.desc("createDate");

            try {
                return dao.get(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return null;
    }

    public boolean updateAgentIdByPlaceId(Long placeId,Long agentId){
        if(placeId != null){
            Conditions conditions = new Conditions(BXSCNOrder.class);
            conditions.and().is("leasePlaceId",placeId);

            Map<String,Object> map = new HashMap<>();
            map.put("leaseAgentId",agentId);

            try {
                return dao.update(map,conditions) > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

    public boolean updateRevertAgentIdByPlaceId(Long placeId,Long agentId){
        if(placeId != null){
            Conditions conditions = new Conditions(BXSCNOrder.class);
            conditions.and().is("revertPlaceId",placeId);

            Map<String,Object> map = new HashMap<>();
            map.put("revertAgentId",agentId);

            try {
                return dao.update(map,conditions) > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

    public boolean paySuccess(BXSCNOrder deviceOrder, OrderLogContent logContent, IBXSCNNetworkService networkService, OperateInfo operateInfo) {
        String errorMsg = null;
        boolean flag = false;
        try {
            flag = dao.insert(deviceOrder) > 0;
            if (!flag) {
                errorMsg = "入库返回失败";
            }
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
            errorMsg = e.getMessage();
        }
        //增加日志
        if (StringTools.isBlank(operateInfo.getOperateNote())) {
            operateInfo.setOperateNote("订单支付成功入库");
        }

        if (flag) {
            BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, logContent, operateInfo, ELogState.Success.index(), null);
            BXSCNWorkThread workThread = new BXSCNWorkThread(dao.getJdbcKey(), deviceOrder, networkService, operateInfo);
            NetworkDeviceWorkThreadPool.self().execute(workThread);
            return true;
        } else {
            log.error("新增共享充电宝订单失败，未触发租借命令，订单信息：{{0:json}}", deviceOrder);
            BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, logContent, operateInfo, ELogState.Fail.index(), errorMsg);
        }
        return false;
    }

    /**
     * 成功归还
     * @param deviceOrder
     * @param operateInfo
     * @return
     */
    public boolean revertFinish(BXSCNOrder deviceOrder, OperateInfo operateInfo){
        if(deviceOrder != null && StringTools.isNotBlank(deviceOrder.getTradeNo())) {
            boolean flag = false;
            String errorMsg = null;

            Conditions conditions = new Conditions(BXSCNOrder.class);
            conditions.and().is("tradeNo", deviceOrder.getTradeNo());
            conditions.and().is("state", BXSCNOrderEnum.State.Lease.index());

            BXSCNOrder updateEntity = new BXSCNOrder();
            updateEntity.setState(BXSCNOrderEnum.State.RevertFinish.index());
            updateEntity.setRevertDeviceSn(deviceOrder.getRevertDeviceSn());
            updateEntity.setRevertSlotNum(deviceOrder.getRevertSlotNum());
            updateEntity.setRevertBindNote(deviceOrder.getRevertBindNote());
            updateEntity.setRevertDeviceTypeId(deviceOrder.getRevertDeviceTypeId());
            updateEntity.setRevertDeviceTypeName(deviceOrder.getRevertDeviceTypeName());
            updateEntity.setRevertPlaceId(deviceOrder.getRevertPlaceId());
            updateEntity.setRevertPlaceName(deviceOrder.getRevertPlaceName());
            updateEntity.setRevertProvince(deviceOrder.getRevertProvince());
            updateEntity.setRevertCity(deviceOrder.getRevertCity());
            updateEntity.setRevertCityArea(deviceOrder.getRevertCityArea());
            updateEntity.setRevertAddress(deviceOrder.getRevertAddress());
            updateEntity.setRevertLatitude(deviceOrder.getRevertLatitude());
            updateEntity.setRevertAgentId(deviceOrder.getRevertAgentId());
            updateEntity.setRevertLongitude(deviceOrder.getRevertLongitude());
            updateEntity.setRevertPower(deviceOrder.getRevertPower());

            updateEntity.setUseDuration(deviceOrder.getUseDuration());
            updateEntity.setEndDate(deviceOrder.getEndDate());
            updateEntity.setMoney(deviceOrder.getMoney());
            updateEntity.setPayMoney(deviceOrder.getPayMoney());
            updateEntity.setWalletMoney(deviceOrder.getWalletMoney());
            updateEntity.setDiscountMoney(deviceOrder.getDiscountMoney());
            updateEntity.setCouponId(deviceOrder.getCouponId());
            updateEntity.setCouponTitle(deviceOrder.getCouponTitle());

            updateEntity.setPayState(deviceOrder.getPayState());    //支付状态

            updateEntity.setOperateState(deviceOrder.getOperateState());    //操作状态

            try {
                if (dao.updateNotNull(updateEntity, conditions) > 0) {
                    flag = true;
                } else {
                    errorMsg = "修改订单失败";
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
                errorMsg = e.getMessage();
            }

            if (flag) {
                //增加日志
                BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, ELogState.Success.index(), null);
                return true;
            } else {
                BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, ELogState.Fail.index(), errorMsg);
            }
        }
        return false;
    }

    /**
     * 完成订单
     * @param deviceOrder
     * @param payMoney
     * @param payServiceFactory
     * @param operateInfo
     * @return -1:处理失败，1:订单退款中，2:订单已完结，需要同步会员订单
     * @throws LogicException
     */
    public int finish(BXSCNOrder deviceOrder, Integer payMoney, IPayServiceFactory payServiceFactory, OperateInfo operateInfo) throws LogicException {
        if (BXSCNOrderEnum.State.RevertFinish.index().equals(deviceOrder.getState()) || BXSCNOrderEnum.State.Close.index().equals(deviceOrder.getState())
                || BXSCNOrderEnum.State.LeaseFail.index().equals(deviceOrder.getState())) {
            log.error("操作订单完成，但设备订单状态不正确，订单号：{{0}}",deviceOrder.getTradeNo());
        }
        if (BXSCNOrderEnum.PayState.Cancel.index().equals(deviceOrder.getPayState()) ||
                BXSCNOrderEnum.PayState.PaySuccess.index().equals(deviceOrder.getPayState())) {
            throw new LogicException("设备订单已完成");
        }

        if(EPayType.WXPay.index().equals(deviceOrder.getPayType())){
            WXPayOrder payOrder = WXPayOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getPayTradeNo());
            if (payOrder == null) {
                throw new LogicException("未找到本地微信支付订单");
            }
            WXPayNormalPayService payService = payServiceFactory.getWXPayNormalPayService(payOrder.getAppId(), BXSCNConstants.BusinessType);
            if (payService == null) {
                throw new LogicException("未配置应用支付服务");
            }
            return finish(deviceOrder,payOrder,payMoney,payService,operateInfo);
        }else if(EPayType.EWallet.index().equals(deviceOrder.getPayType())){
            Long walletMoney = NumberTools.changeMoneyLi(NumberTools.changeMoney(payMoney));
            return finish(deviceOrder,walletMoney,payServiceFactory.getMemberWalletService(),operateInfo);
        }
        return -1;
    }

    private int finish(BXSCNOrder deviceOrder, WXPayOrder payOrder, Integer payMoney, WXPayNormalPayService payService, OperateInfo operateInfo) throws LogicException {
        if (EOrderOperateState.NoOperation.index().equals(deviceOrder.getOperateState())) {
            Integer refundMoney = 0;
            if (payOrder.getPayMoney() < payMoney) {
                throw new LogicException("客户支付金额小于结算金额，订单无法完成");
            } else if (payOrder.getPayMoney() > payMoney) {
                //单位转化，厘变分
                refundMoney = payOrder.getPayMoney() - payMoney;
            }

            Integer operateState = ELogState.Success.index();
            String errorMsg = null;

            Long money = NumberTools.changeMoneyLi(NumberTools.changeMoney(payMoney));

            Conditions conditions = new Conditions(BXSCNOrder.class);
            conditions.and().is("tradeNo", deviceOrder.getTradeNo());
            conditions.and().is("operateState", deviceOrder.getOperateState());
            conditions.and().is("state", deviceOrder.getState());

            BXSCNOrder updateEntity = new BXSCNOrder();
            updateEntity.setTradeNo(deviceOrder.getTradeNo());
            if (BXSCNOrderEnum.State.WaitStart.index().equals(deviceOrder.getState())
                    || BXSCNOrderEnum.State.Opening.index().equals(deviceOrder.getState())) {
                updateEntity.setState(BXSCNOrderEnum.State.Close.index());
            } else if (BXSCNOrderEnum.State.Lease.index().equals(deviceOrder.getState())) {
                updateEntity.setState(BXSCNOrderEnum.State.Close.index());
            }
            updateEntity.setMoney(money);
            updateEntity.setPayMoney(payMoney);
            updateEntity.setFinishDate(new Date());

            try {
                if (dao.updateNotNull(updateEntity) <= 0) {
                    operateState = ELogState.Fail.index();
                    errorMsg = "修改数据库失败";
                }
            } catch (SQLException e) {
                operateState = ELogState.Fail.index();
                errorMsg = e.getMessage();
                log.error(e.getMessage(), e);
            }

            //记录日志
            BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, operateState, errorMsg);

            if (ELogState.Success.index().equals(operateState)) {
                if (refundMoney > 0) {
                    if (noOperateTo(deviceOrder.getTradeNo(), EOrderOperateState.Finishing.index())) {
                        //触发退款
                        WXRefundOrder refundOrder = WXRefundOrderService.self(deviceOrder.getCreateDate()).createRefundOrder(payOrder, refundMoney, operateInfo.getOperateNote());
                        WXPayNormalRefundResponse externalResult = payService.applyRefundOrder(refundOrder);
                        if (externalResult != null) {
                            if (StringTools.isNotBlank(externalResult.getCode()) && StringTools.isNotBlank(externalResult.getMessage())) {
                                operateState = ELogState.Fail.index();
                                errorMsg = externalResult.getMessage();
                            } else if (EWXPayNormalRefundState.SUCCESS.name().equals(externalResult.getStatus())) {
                                log.info("{{0}}订单微信直接退款成功，返回信息：{{1}}", payOrder.getTradeNo(), JsonTools.toJson(externalResult));
                            } else if (EWXPayNormalRefundState.CLOSED.name().equals(externalResult.getStatus()) ||
                                    EWXPayNormalRefundState.ABNORMAL.name().equals(externalResult.getStatus())) {
                                operateState = ELogState.Fail.index();
                                errorMsg = "退款订单已关闭或异常";
                                log.error("{{0}}订单微信退款失败，返回信息：{{1}}", payOrder.getTradeNo(), JsonTools.toJson(externalResult));
                            }
                        } else {
                            operateState = ELogState.Fail.index();
                            errorMsg = "微信退款失败，无响应";
                            log.error("{{0}}订单微信退款失败，无返回信息", payOrder.getTradeNo());
                        }

                        if (ELogState.Fail.index().equals(operateState)) {
                            //失败回滚数据库
                            faceOperateState(deviceOrder.getTradeNo(), EOrderOperateState.NoOperation.index());
                        }
                    } else {
                        operateState = ELogState.Fail.index();
                        errorMsg = "完成时锁定订单失败";
                    }

                    //记录日志
                    operateInfo.setOperateNote("第三方订单退款");
                    BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, operateState, errorMsg);
                }
            }

            if (ELogState.Success.index().equals(operateState)) {
                if (refundMoney > 0) {
                    return 1;
                } else {
                    return 2;
                }
            }
        }
        return -1;
    }

    private int finish(BXSCNOrder deviceOrder, Long walletMoney, IMemberWalletService memberWalletService, OperateInfo operateInfo) throws LogicException {
        if(EOrderOperateState.NoOperation.index().equals(deviceOrder.getOperateState())) {
            Long refundMoney = 0L;
            if (deviceOrder.getWalletMoney() < walletMoney) {
                throw new LogicException("客户支付金额小于结算金额，订单无法完成");
            } else if (deviceOrder.getWalletMoney() > walletMoney) {
                refundMoney = deviceOrder.getWalletMoney() - walletMoney;
            }

            Integer operateState = ELogState.Success.index();
            String errorMsg = null;

            //支付金额不变，只修改订单状态
            Conditions conditions = new Conditions(BXSCNOrder.class);
            conditions.and().is("tradeNo", deviceOrder.getTradeNo());
            conditions.and().is("operateState", deviceOrder.getOperateState());
            conditions.and().is("state", deviceOrder.getState());

            BXSCNOrder updateEntity = new BXSCNOrder();
            updateEntity.setTradeNo(deviceOrder.getTradeNo());
            updateEntity.setMoney(walletMoney);
            updateEntity.setWalletMoney(walletMoney);
            updateEntity.setFinishDate(new Date());
            if (BXSCNOrderEnum.State.WaitStart.index().equals(deviceOrder.getState())
                    || BXSCNOrderEnum.State.Opening.index().equals(deviceOrder.getState())) {
                updateEntity.setState(BXSCNOrderEnum.State.Close.index());
            } else if (BXSCNOrderEnum.State.Lease.index().equals(deviceOrder.getState())) {
                updateEntity.setState(BXSCNOrderEnum.State.Close.index());
            }

            JdbcSession.begin();
            try {
                if (dao.updateNotNull(updateEntity) > 0) {
                    if(refundMoney > 0) {
                        if (memberWalletService.addMoney(deviceOrder.getMemberId(), refundMoney, operateInfo)) {
                            JdbcSession.commit();
                        } else {
                            operateState = ELogState.Fail.index();
                            errorMsg = "修改会员余额失败";
                        }
                    }else{
                        JdbcSession.commit();
                    }
                }else{
                    operateState = ELogState.Fail.index();
                    errorMsg = "修改数据库失败";
                }
            } catch (SQLException e) {
                operateState = ELogState.Fail.index();
                errorMsg = e.getMessage();
                log.error(e.getMessage(), e);
            } finally {
                JdbcSession.end();
            }

            //记录日志
            BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, operateState, errorMsg);
            if (ELogState.Success.index().equals(operateState)) {
                return 2;
            }
        }
        return -1;
    }

    public int refund(BXSCNOrder deviceOrder, Integer refundMoney, IPayServiceFactory payServiceFactory, OperateInfo operateInfo)throws LogicException{
        if (!BXSCNOrderEnum.PayState.PaySuccess.index().equals(deviceOrder.getPayState())) {
            throw new LogicException("支付未成功");
        }

        if(EPayType.WXPay.index().equals(deviceOrder.getPayType())){
            WXPayOrder payOrder = WXPayOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getPayTradeNo());
            if (payOrder == null) {
                throw new LogicException("未找到本地微信支付订单");
            }
            WXPayNormalPayService normalPayService = payServiceFactory.getWXPayNormalPayService(payOrder.getAppId(), BXSCNConstants.BusinessType);
            if (normalPayService == null) {
                throw new LogicException("未找到微信支付服务");
            }
            return refund(deviceOrder,payOrder,refundMoney,normalPayService,operateInfo);
        }else if(EPayType.EWallet.index().equals(deviceOrder.getPayType())){

        }
        return -1;
    }

    private int refund(BXSCNOrder deviceOrder, WXPayOrder payOrder, Integer refundMoney, WXPayNormalPayService normalPayService, OperateInfo operateInfo) throws LogicException {
        if (deviceOrder.getPayMoney() < refundMoney) {
            throw new LogicException("没有足够的支付金额进行撤销");
        }
        Integer payMoney = deviceOrder.getPayMoney() - refundMoney;
        if (payMoney <= 0) {
            throw new LogicException("退款金额超界");
        }

        Integer operateState = ELogState.Success.index();
        String errorMsg = null;

        if(noOperateTo(deviceOrder.getTradeNo(),EOrderOperateState.Refunding.index())){
            try {
                //触发退款
                WXRefundOrder refundOrder = WXRefundOrderService.self(deviceOrder.getCreateDate()).createRefundOrder(payOrder, refundMoney, operateInfo.getOperateNote());
                WXPayNormalRefundResponse externalResult = normalPayService.applyRefundOrder(refundOrder);
                if (externalResult != null) {
                    if(StringTools.isNotBlank(externalResult.getCode()) && StringTools.isNotBlank(externalResult.getMessage())){
                        operateState = ELogState.Fail.index();
                        errorMsg = externalResult.getMessage();
                    }else if (EWXPayNormalRefundState.SUCCESS.name().equals(externalResult.getStatus())){
                        log.info("{{0}}订单微信直接退款成功，返回信息：{{1}}", payOrder.getTradeNo(), JsonTools.toJson(externalResult));
                    }else if(EWXPayNormalRefundState.CLOSED.name().equals(externalResult.getStatus()) ||
                            EWXPayNormalRefundState.ABNORMAL.name().equals(externalResult.getStatus())) {
                        operateState = ELogState.Fail.index();
                        errorMsg = "退款订单已关闭或异常";
                        log.error("{{0}}订单微信退款失败，返回信息：{{1}}", payOrder.getTradeNo(), JsonTools.toJson(externalResult));
                    }
                } else {
                    operateState = ELogState.Fail.index();
                    errorMsg = "微信退款失败，无响应";
                    log.error("{{0}}订单微信退款失败，无返回信息", payOrder.getTradeNo());
                }
            } catch (Exception e) {
                operateState = ELogState.Fail.index();
                errorMsg = e.getMessage();
                log.error(e.getMessage(), e);
            }finally {
                faceOperateState(deviceOrder.getTradeNo(),EOrderOperateState.NoOperation.index());
            }
        }else{
            operateState = ELogState.Fail.index();
            errorMsg = "退款时锁定订单失败";
        }

        //增加日志
        BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, operateState, errorMsg);
        if(ELogState.Success.index().equals(operateState)) {
            return 1;
        }
        return -1;
    }

    public int cancel(BXSCNOrder deviceOrder, IPayServiceFactory payServiceFactory, OperateInfo operateInfo) throws LogicException {
        if (BXSCNOrderEnum.PayState.Cancel.index().equals(deviceOrder.getPayState())) {
            throw new LogicException("设备订单已撤销");
        }

        if (BXSCNOrderEnum.PayState.PaySuccess.index().equals(deviceOrder.getPayState()) || BXSCNOrderEnum.PayState.DepositSuccess.index().equals(deviceOrder.getPayState())) {
            if (EPayType.WXPay.index().equals(deviceOrder.getPayType())) {
                WXPayOrder payOrder = WXPayOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getPayTradeNo());
                if (payOrder == null) {
                    throw new LogicException("未找到本地微信支付订单");
                }
                WXPayNormalPayService payService = payServiceFactory.getWXPayNormalPayService(payOrder.getAppId(),BXSCNConstants.BusinessType);
                if (payService == null) {
                    throw new LogicException("未配置应用支付服务");
                }
                return cancel(deviceOrder, payOrder, payService, operateInfo);
            } else if (EPayType.EWallet.index().equals(deviceOrder.getPayType())) {
                return cancel(deviceOrder, payServiceFactory.getMemberWalletService(), operateInfo);
            }
        }else{
            throw new LogicException("设备订单状态为："+deviceOrder.getPayStateName()+"，无法查询");
        }
        return -1;
    }

    private int cancel(BXSCNOrder deviceOrder, WXPayOrder payOrder, WXPayNormalPayService payService, OperateInfo operateInfo) throws LogicException {
        if(EOrderOperateState.NoOperation.index().equals(deviceOrder.getOperateState())) {
            Integer refundMoney = deviceOrder.getPayMoney();
            Integer operateState = ELogState.Success.index();
            String errorMsg = null;

            if (refundMoney > 0) {
                if(noOperateTo(deviceOrder.getTradeNo(),EOrderOperateState.Cancelling.index())) {
                        //触发退款
                        try {
                            WXRefundOrder refundOrder = WXRefundOrderService.self(deviceOrder.getCreateDate()).createRefundOrder(payOrder, refundMoney, operateInfo.getOperateNote());
                            if (refundOrder != null) {
                                WXPayNormalRefundResponse externalResult = payService.applyRefundOrder(refundOrder);
                                if (externalResult != null) {
                                    if(StringTools.isNotBlank(externalResult.getCode()) && StringTools.isNotBlank(externalResult.getMessage())){
                                        operateState = ELogState.Fail.index();
                                        errorMsg = externalResult.getMessage();
                                    }else if (EWXPayNormalRefundState.SUCCESS.name().equals(externalResult.getStatus())){
                                        log.info("{{0}}订单微信直接退款成功，返回信息：{{1}}", payOrder.getTradeNo(), JsonTools.toJson(externalResult));
                                    }else if(EWXPayNormalRefundState.CLOSED.name().equals(externalResult.getStatus()) ||
                                            EWXPayNormalRefundState.ABNORMAL.name().equals(externalResult.getStatus())) {
                                        operateState = ELogState.Fail.index();
                                        errorMsg = "退款订单已关闭或异常";
                                        log.error("{{0}}订单微信退款失败，返回信息：{{1}}", payOrder.getTradeNo(), JsonTools.toJson(externalResult));
                                    }
                                } else {
                                    operateState = ELogState.Fail.index();
                                    errorMsg = "微信退款失败，无响应";
                                    log.error("{{0}}订单微信退款失败，无返回信息", payOrder.getTradeNo());
                                }
                            } else {
                                operateState = ELogState.Fail.index();
                                errorMsg = "创建微信退款订单失败";
                            }
                        } catch (Exception e) {
                            log.error(e.getMessage(), e);
                            operateState = ELogState.Fail.index();
                            errorMsg = e.getMessage();
                        }

                        if (ELogState.Fail.index().equals(operateState)) {
                            //失败回滚数据库
                            faceOperateState(deviceOrder.getTradeNo(),EOrderOperateState.NoOperation.index());
                        }

                }else {
                    operateState = ELogState.Fail.index();
                    errorMsg = "退款时锁定订单失败";
                }

                //记录日志
                operateInfo.setOperateNote("【撤销订单】" + operateInfo.getOperateNote());
                BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, operateState, errorMsg);
                if (ELogState.Success.index().equals(operateState)) {
                    return 1;
                }
            } else {
                Conditions conditions = new Conditions(BXSCNOrder.class);
                conditions.and().is("tradeNo", deviceOrder.getTradeNo());
                conditions.and().is("operateState", deviceOrder.getOperateState());
                conditions.and().is("state", deviceOrder.getState());

                BXSCNOrder updateEntity = new BXSCNOrder();
                updateEntity.setTradeNo(deviceOrder.getTradeNo());
                updateEntity.setPayMoney(0);
                updateEntity.setPayState(BXSCNOrderEnum.PayState.Cancel.index());
                //非终结状态，则修改为失败状态
                if (BXSCNOrderEnum.State.Lease.index().equals(deviceOrder.getState())) {
                    updateEntity.setState(BXSCNOrderEnum.State.Close.index());
                } else if (BXSCNOrderEnum.State.WaitStart.index().equals(deviceOrder.getState())
                        || BXSCNOrderEnum.State.Opening.index().equals(deviceOrder.getState())) {
                    updateEntity.setState(BXSCNOrderEnum.State.LeaseFail.index());
                }

                try {
                    if (dao.updateNotNull(updateEntity) <= 0) {
                        operateState = ELogState.Fail.index();
                        errorMsg = "修改数据库失败";
                    }
                } catch (SQLException e) {
                    operateState = ELogState.Fail.index();
                    errorMsg = e.getMessage();
                    log.error(e.getMessage(), e);
                }

                //记录日志
                operateInfo.setOperateNote("【撤销订单】" + operateInfo.getOperateNote());
                BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, operateState, errorMsg);
                if (ELogState.Success.index().equals(operateState)) {
                    return 2;
                }
            }
        }
        return -1;
    }

    private int cancel(BXSCNOrder deviceOrder, IMemberWalletService memberWalletService, OperateInfo operateInfo)throws LogicException {
        if(EOrderOperateState.NoOperation.index().equals(deviceOrder.getOperateState())) {
            Long refundMoney = deviceOrder.getWalletMoney();
            Integer operateState = ELogState.Success.index();
            String errorMsg = null;

            Conditions conditions = new Conditions(BXSCNOrder.class);
            conditions.and().is("tradeNo", deviceOrder.getTradeNo());
            conditions.and().is("operateState", deviceOrder.getOperateState());
            conditions.and().is("state", deviceOrder.getState());

            BXSCNOrder updateEntity = new BXSCNOrder();
            updateEntity.setTradeNo(deviceOrder.getTradeNo());
            updateEntity.setWalletMoney(0L);
            updateEntity.setPayState(BXSCNOrderEnum.PayState.Cancel.index());
            updateEntity.setCancelDate(new Date());

            //非终结状态，则修改为失败状态
            if (BXSCNOrderEnum.State.Lease.index().equals(deviceOrder.getState())) {
                updateEntity.setState(BXSCNOrderEnum.State.Close.index());
            } else if (BXSCNOrderEnum.State.WaitStart.index().equals(deviceOrder.getState())
                    || BXSCNOrderEnum.State.Opening.index().equals(deviceOrder.getState())) {
                updateEntity.setState(BXSCNOrderEnum.State.LeaseFail.index());
            }

            JdbcSession.begin();
            try {
                if (dao.updateNotNull(updateEntity) > 0) {
                    if (refundMoney > 0) {
                        if (memberWalletService.addMoney(deviceOrder.getMemberId(), refundMoney, operateInfo)) {
                            JdbcSession.commit();
                        } else {
                            operateState = ELogState.Fail.index();
                            errorMsg = "新增会员钱包余额失败";
                        }
                    } else {
                        JdbcSession.commit();
                    }
                } else {
                    operateState = ELogState.Fail.index();
                    errorMsg = "修改设备订单失败";
                }
            } catch (SQLException e) {
                operateState = ELogState.Fail.index();
                errorMsg = e.getMessage();
                log.error(e.getMessage(), e);
            } finally {
                JdbcSession.end();
            }

            //记录日志
            BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, operateState, errorMsg);
            if (ELogState.Success.index().equals(operateState)) {
                return 2;
            }
        }
        return -1;
    }

    public boolean waitStartToOpening(String tradeNo){
        if(StringTools.isNotBlank(tradeNo)){
            Conditions conditions = new Conditions(BXSCNOrder.class);
            conditions.and().is("tradeNo",tradeNo);
            conditions.and().is("state", BXSCNOrderEnum.State.WaitStart.index());

            BXSCNOrder updateEntity = new BXSCNOrder();
            updateEntity.setState(BXSCNOrderEnum.State.Opening.index());
            updateEntity.setStartDate(new Date());

            try {
                if(dao.updateNotNull(updateEntity,conditions) > 0){
                    return true;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

    public boolean openingSuccess(BXSCNOrder deviceOrder, OperateInfo operateInfo){
        if(deviceOrder != null && StringTools.isNotBlank(deviceOrder.getTradeNo())){
            Conditions conditions = new Conditions(BXSCNOrder.class);
            conditions.and().is("tradeNo",deviceOrder.getTradeNo());
            conditions.and().is("state", BXSCNOrderEnum.State.Opening.index());

            BXSCNOrder updateEntity = new BXSCNOrder();
            updateEntity.setState(BXSCNOrderEnum.State.Lease.index());
            updateEntity.setLeaseSlotNum(deviceOrder.getLeaseSlotNum());
            updateEntity.setLeasePower(deviceOrder.getLeasePower());
            updateEntity.setPortableBatterySn(deviceOrder.getPortableBatterySn());

            boolean flag = false;
            String errorMsg = null;

            try {
                if(dao.updateNotNull(updateEntity,conditions) > 0){
                    deviceOrder.setState(updateEntity.getState());
                    deviceOrder.setLeaseSlotNum(updateEntity.getLeaseSlotNum());
                    deviceOrder.setLeasePower(updateEntity.getLeasePower());
                    deviceOrder.setPortableBatterySn(updateEntity.getPortableBatterySn());
                    flag = true;
                } else {
                    errorMsg = "修改订单失败";
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }

            if (flag) {
                //增加日志
                BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, ELogState.Success.index(), null);
                return true;
            } else {
                BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, ELogState.Fail.index(), errorMsg);
            }
        }
        return false;
    }

    public boolean openingFail(BXSCNOrder deviceOrder,Integer leaseErrorState, OperateInfo operateInfo){
        if(deviceOrder != null && StringTools.isNotBlank(deviceOrder.getTradeNo())) {
            boolean flag = false;
            String errorMsg = null;
            Conditions conditions = new Conditions(BXSCNOrder.class);
            conditions.and().is("tradeNo", deviceOrder.getTradeNo());
            conditions.and().is("state", BXSCNOrderEnum.State.Opening.index());

            BXSCNOrder updateEntity = new BXSCNOrder();
            updateEntity.setState(BXSCNOrderEnum.State.LeaseFail.index());
            updateEntity.setLeaseErrorState(leaseErrorState);

            try {
                if (dao.updateNotNull(updateEntity, conditions) > 0) {
                    flag = true;
                } else {
                    errorMsg = "修改订单失败";
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
                errorMsg = e.getMessage();
            }

            if (flag) {
                //增加日志
                BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, ELogState.Success.index(), null);
            } else {
                BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, ELogState.Fail.index(), errorMsg);
            }
        }
        return false;
    }

    public int refundSuccess(WXRefundOrder refundOrder,OperateInfo operateInfo){
        BXSCNOrder deviceOrder = getByTradeNo(refundOrder.getBusinessTradeNo());
        if(deviceOrder == null){
            log.error("退款成功，未找到设备订单，退款订单信息：{{0:json}}",refundOrder);
        }
        if(EOrderOperateState.Cancelling.index().equals(deviceOrder.getOperateState())){
            Conditions conditions = new Conditions(BXSCNOrder.class);
            conditions.and().is("tradeNo",refundOrder.getBusinessTradeNo());
            conditions.and().is("operateState",EOrderOperateState.Cancelling.index());

            BXSCNOrder updateEntity = new BXSCNOrder();
            updateEntity.setOperateState(EOrderOperateState.NoOperation.index());
            updateEntity.setPayState(BXSCNOrderEnum.PayState.Cancel.index());
            updateEntity.setMoney(0L);
            updateEntity.setPayMoney(0);
            updateEntity.setCancelDate(new Date());

            Integer logState = ELogState.Fail.index();
            String errorMsg = "修改订单状态失败";
            try {
                if(dao.updateNotNull(updateEntity,conditions) > 0){
                    logState = ELogState.Success.index();
                    errorMsg = null;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
                errorMsg = e.getMessage();
            }

            BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, logState, errorMsg);
            if(ELogState.Success.index().equals(logState)){
                return 1;
            }
        }else if(EOrderOperateState.Finishing.index().equals(deviceOrder.getOperateState())){
            Conditions conditions = new Conditions(BXSCNOrder.class);
            conditions.and().is("tradeNo",refundOrder.getBusinessTradeNo());
            conditions.and().is("operateState",EOrderOperateState.Finishing.index());

            BXSCNOrder updateEntity = new BXSCNOrder();
            updateEntity.setOperateState(EOrderOperateState.NoOperation.index());
            updateEntity.setPayState(BXSCNOrderEnum.PayState.PaySuccess.index());

            Integer logState = ELogState.Fail.index();
            String errorMsg = "修改订单状态失败";
            try {
                if(dao.updateNotNull(updateEntity,conditions) > 0){
                    logState = ELogState.Success.index();
                    errorMsg = null;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }

            BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, logState, errorMsg);
            if(ELogState.Success.index().equals(logState)){
                return 3;
            }
        }else if(EOrderOperateState.Refunding.index().equals(deviceOrder.getOperateState())){
            Conditions conditions = new Conditions(BXSCNOrder.class);
            conditions.and().is("tradeNo",refundOrder.getBusinessTradeNo());
            conditions.and().is("operateState",EOrderOperateState.Refunding.index());

            //计算退款金额
            Long money = deviceOrder.getMoney();
            Integer payMoney = deviceOrder.getPayMoney();

            if(refundOrder.getRefundMoney() > 0) {
                payMoney = payMoney - refundOrder.getRefundMoney();
                if (payMoney > 0) {
                    money = money - NumberTools.changeMoneyLi(NumberTools.changeMoney(payMoney));
                } else {
                    //全部退款
                    payMoney = 0;
                    money = 0L;
                }
            }

            BXSCNOrder updateEntity = new BXSCNOrder();
            updateEntity.setMoney(money);
            updateEntity.setPayMoney(payMoney);
            updateEntity.setOperateState(EOrderOperateState.NoOperation.index());

            Integer logState = ELogState.Fail.index();
            String errorMsg = "修改订单状态失败";
            try {
                if(dao.updateNotNull(updateEntity,conditions) > 0){
                    logState = ELogState.Success.index();
                    errorMsg = null;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }

            BXSCNOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, logState, errorMsg);
            if(ELogState.Success.index().equals(logState)){
                return 3;
            }
        }
        return -1;
    }

    public boolean refundFail(WXRefundOrder refundOrder,OperateInfo operateInfo){
        BXSCNOrder deviceOrder = getByTradeNo(refundOrder.getBusinessTradeNo());
        if(deviceOrder == null){
            log.error("退款成功，未找到设备订单，退款订单信息：{{0:json}}",refundOrder);
        }

        if(EOrderOperateState.Cancelling.index().equals(deviceOrder.getOperateState())){
            Conditions conditions = new Conditions(BXSCNOrder.class);
            conditions.and().is("tradeNo",refundOrder.getBusinessTradeNo());
            conditions.and().is("operateState",EOrderOperateState.Cancelling.index());

            BXSCNOrder updateEntity = new BXSCNOrder();
            updateEntity.setOperateState(EOrderOperateState.NoOperation.index());
            try {
                if(dao.updateNotNull(updateEntity,conditions) > 0){
                    return true;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }else if(EOrderOperateState.Refunding.index().equals(deviceOrder.getOperateState())) {
            Conditions conditions = new Conditions(BXSCNOrder.class);
            conditions.and().is("tradeNo", refundOrder.getBusinessTradeNo());
            conditions.and().is("operateState", EOrderOperateState.Refunding.index());

            BXSCNOrder updateEntity = new BXSCNOrder();
            updateEntity.setOperateState(EOrderOperateState.NoOperation.index());
            try {
                if (dao.updateNotNull(updateEntity, conditions) > 0) {
                    return true;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }else if(EOrderOperateState.Finishing.index().equals(deviceOrder.getOperateState())) {
            Conditions conditions = new Conditions(BXSCNOrder.class);
            conditions.and().is("tradeNo", refundOrder.getBusinessTradeNo());
            conditions.and().is("operateState", EOrderOperateState.Finishing.index());

            BXSCNOrder updateEntity = new BXSCNOrder();
            updateEntity.setOperateState(EOrderOperateState.NoOperation.index());

            try {
                if (dao.updateNotNull(updateEntity, conditions) > 0) {
                    return true;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return false;
    }

    public boolean forceUpdateMoney(String tradeNo,Long money,Integer payMoney){
        if(StringTools.isNotBlank(tradeNo) && (money != null || payMoney != null)){
            BXSCNOrder deviceOrder = new BXSCNOrder();
            deviceOrder.setTradeNo(tradeNo);
            deviceOrder.setMoney(money);
            deviceOrder.setPayMoney(payMoney);

            try {
                return dao.updateNotNull(deviceOrder) > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

    public boolean faceOperateState(String tradeNo,Integer operateState){
        if(StringTools.isNotBlank(tradeNo) && operateState != null){
            BXSCNOrder deviceOrder = new BXSCNOrder();
            deviceOrder.setTradeNo(tradeNo);
            deviceOrder.setOperateState(operateState);

            try {
                return dao.updateNotNull(deviceOrder) > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

    public boolean noOperateTo(String tradeNo,Integer operateState){
        if(StringTools.isNotBlank(tradeNo) && operateState != null){
            Conditions conditions = new Conditions(BXSCNOrder.class);
            conditions.and().is("tradeNo",tradeNo);
            conditions.and().is("operateState",EOrderOperateState.NoOperation.index());

            BXSCNOrder deviceOrder = new BXSCNOrder();
            deviceOrder.setOperateState(operateState);

            try {
                return dao.updateNotNull(deviceOrder,conditions) > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }
}
